package cn.xudy.async.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * Created by Ulegal on 2017/10/24.
 */

@Configuration
@EnableAsync
public class TaskExecutePool {

    @Autowired
    private TaskThreadPoolConfig config;

    /**
     * 线程池是为突然大量爆发的线程设计的，通过有限的几个固定线程为大量的操作服务，减少了创建和销毁线程所需的时间，
     * 从而提高效率。如果一个线程的时间非常长，就没必要用线程池了(不是不能作长时间操作，而是不宜。)，
     * 况且还不能控制线程池中线程的开始、挂起、和中止。
     * 二、利用线程池启动线程
     Thread udpThread = new Thread(udp);
     poolTaskExecutor.execute(udpThread);
     获取当前线程池活动的线程数：
     int count = poolTaskExecutor.getActiveCount();
     logger.debug("[x] - now threadpool active threads totalNum : " +count);
     三、配置解释
     当一个任务通过execute(Runnable)方法欲添加到线程池时：
     1、 如果此时线程池中的数量小于corePoolSize，即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
     2、 如果此时线程池中的数量等于 corePoolSize，但是缓冲队列 workQueue未满，那么任务被放入缓冲队列。
     3、如果此时线程池中的数量大于corePoolSize，缓冲队列workQueue满，并且线程池中的数量小于maximumPoolSize，建新的线程来处理被添加的任务。
     4、 如果此时线程池中的数量大于corePoolSize，缓冲队列workQueue满，并且线程池中的数量等于maximumPoolSize，那么通过 handler所指定的策略来处理此任务。
     也就是：处理任务的优先级为：核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize，如果三者都满了，使用handler处理被拒绝的任务。
     5、 当线程池中的线程数量大于 corePoolSize时，如果某线程空闲时间超过keepAliveTime，线程将被终止。这样，线程池可以动态的调整池中的线程数。
     allowCoreThreadTimeout：允许核心线程超时
     rejectedExecutionHandler：任务拒绝处理器
     * @return
     */
    /**
     *  allowCoreThreadTimeout：允许核心线程超时
     rejectedExecutionHandler：任务拒绝处理器

     两种情况会拒绝处理任务：
     当线程数已经达到maxPoolSize，切队列已满，会拒绝新任务
     当线程池被调用shutdown()后，会等待线程池里的任务执行完毕，再shutdown。如果在调用shutdown()和线程池真正shutdown之间提交任务，会拒绝新任务
     线程池会调用rejectedExecutionHandler来处理这个任务。如果没有设置默认是AbortPolicy，会抛出异常
     ThreadPoolExecutor类有几个内部实现类来处理这类情况：
     AbortPolicy 丢弃任务，抛运行时异常
     CallerRunsPolicy 执行任务
     DiscardPolicy 忽视，什么都不会发生
     DiscardOldestPolicy 从队列中踢出最先进入队列（最后一个执行）的任务
     实现RejectedExecutionHandler接口，可自定义处理器

     * @return
     */
//    @Bean
//    public Executor myTaskAsyncPool() {
//        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//        executor.setCorePoolSize(config.getCorePoolSize());//线程池维护线程的最少数量
//        executor.setMaxPoolSize(config.getMaxPoolSize());//线程池维护线程的最大数量
//        executor.setQueueCapacity(config.getQueueCapacity());//线程池所使用的缓冲队列
//        executor.setKeepAliveSeconds(config.getKeepAliveSeconds());//线程池维护线程所允许的空闲时间
//        executor.setThreadNamePrefix("MyExecutor-");
//        System.out.println("------------------------》》》开启线程池");
//        // rejection-policy：当pool已经达到max size的时候，如何处理新任务
//        // CALLER_RUNS：不在新线程中执行任务，而是由调用者所在的线程来执行
//        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//        executor.initialize();
//        return executor;
//    }

}
